﻿using System;
using System.Collections.Generic;
using System.Threading;

namespace wspol_zad3
{
    public class Buffors
    {
        //Bufory cykliczne
        private int[] b1;
        private int[] b2;

        //nastepna wolna pozycja
        private int b1PositionProducer;
        //nastepny element do konsumpcji
        private int b1PositionConsumer;

        private int b2Position;

        //Ile elementow znajduje sie aktualnie w tablicy
        private int b1Count;
        private int b2Count;

        //Obiekty synchronizacji
        /*private readonly object producer;
        private readonly object consumer;
        private readonly object cleared;
        private readonly object clear;*/

        public Buffors(int b1Cnt, int b2Cnt)
        {
            b1 = new int[b1Cnt];
            b2 = new int[b2Cnt];

            /*producer = new object();
            consumer = new object();
            clear = new object();
            cleared = new object();*/

            b1Count = 0;
            b2Count = 0;
            b1PositionProducer = 0;
            b1PositionConsumer = 0;
            b2Position = 0;
        }

        //Wstaw do b1
        /*
         * Wstaw do b1 jezeli nie jest pelny.
         * Jezeli jest pelny to czekaj.
         * wstaw na pozycje b1Position i ustaw odpowiednia nastepna pozycje
         * zwieksz liczbe elementow
         * zasygnalizuj konsumenta
         */
        public void b1Put(int elem)
        {
            lock (b1)
            {
                //lock (consumer)
                {
                    while (b1Count >= b1.Length) Monitor.Wait(b1);
                    b1[b1PositionProducer] = elem;
                    b1PositionProducer = (b1PositionProducer + 1) % b1.Length;
                    b1Count++;
                    Monitor.Pulse(b1);
                }
            }
        }

        //Pobierz z b1
        /*
         * jezeli jest pusty czekaj
         * pobierz z b1PositionConsumer i ustaw odpowiednio nastepny
         * zmniejsz liczbe elementow b1
         * zasygnalizuj producenta
         */
        public int b1Get()
        {
            int ret = -1; ;
            //lock (consumer)
            {
                lock (b1)
                {
                    while (b1Count == 0) Monitor.Wait(b1);
                    ret = b1[b1PositionConsumer];
                    b1[b1PositionConsumer] = -1;
                    b1PositionConsumer = (b1PositionConsumer + 1) % b1.Length;
                    b1Count--;
                    Monitor.Pulse(b1);
                }
            }

            return ret;
        }

        //Wstaw do b2
        /*
         * Jezeli b2 pelne czekaj
         * dodaj element na b2Position i ustaw nowa pozycje
         * zwieksz liczbe elementow b2
         * jezeli licza elementow == pojenosci sygnalizuj clear
         */
        public void b2Put(int elem)
        {
            //lock (cleared)
            {
                lock (b2)
                {
                    while (b2Count >= b2.Length) Monitor.Wait(b2);
                    b2[b2Position] = elem;
                    b2Position = (b2Position + 1) % b2.Length;
                    b2Count++;
                    if (b2Count == b2.Length) Monitor.Pulse(b2);
                }
            }
        }

        //Oproznij b2
        /*
         * Jezeli b2 nie pelne czekaj
         * ustaw liczbe elementow na 0 w b2
         * ustaw -1 na elementach w b2
         * sygnalizuj clear
         */
        public void b2Clear()
        {
            lock (b2)
            {
                //lock (cleared)
                {
                    while (b2Count < b2.Length) Monitor.Wait(b2);
                    b2Position = 0;
                    b2Count = 0;

                    for (int i = 0; i < b2.Length; i++)
                        b2[i] = -1;

                    Monitor.Pulse(b2);
                }
            }
        }

        public string PrepareStringData()
        {
            string s = "";
            lock(b1)
                lock(b2)
                        {
                            string s1 = "B1: ";
                            string s2 = "B2: ";

                            for (int i = 0; i < b1.Length; i++)
                                s1 += b1[i].ToString() + ";";

                            for (int i = 0; i < b2.Length; i++)
                                s2 += b2[i].ToString() + ";";

                            s1 += "\n\r";
                            s2 += "\n\r";

                            s = s1 + s2;
                        }
            return s;
        }
    }
}
